import { Request, Response, NextFunction } from 'express';
import roleService from '@/services/system/role.service';
import menuService from '@/services/system/menu.service';
import { AuthRequest } from '@/types';
import { DATA_SCOPE } from '@/middlewares/dataScope.middleware';
import NodeCache from 'node-cache';
import { getLogger } from '@/utils/logger';

const logger = getLogger('permission-middleware');

// 权限缓存，提高权限检查性能
// 设置缓存时间为60分钟，检查周期为120分钟
const permissionCache = new NodeCache({
  stdTTL: 60 * 60, // 默认缓存时间（秒）
  checkperiod: 120 * 60 // 检查过期缓存的周期（秒）
});

/**
 * 角色权限校验中间件
 * @param roles 角色列表
 */
export const roleMiddleware = (roles: string[]) => {
  return async (req: AuthRequest, res: Response, next: NextFunction): Promise<Response | void> => {
    try {
      // 获取当前用户信息
      const user = req.user;
      
      if (!user) {
        return res.status(401).json({
          code: 401,
          msg: '用户未登录'
        });
      }
      
      // 超级管理员拥有所有权限
      if (user.roles.includes('admin')) {
        next();
        return;
      }
      
      // 检查用户是否具有需要的角色
      const hasRole = roles.some(role => user.roles.includes(role));
      
      if (!hasRole) {
        return res.status(403).json({
          code: 403,
          msg: '权限不足，需要特定角色'
        });
      }
      
      next();
      return;
    } catch (error) {
      next(error);
      return;
    }
  };
};

/**
 * 权限标识校验中间件
 * @param permission 权限标识
 */
export const permissionMiddleware = (permission: string) => {
  return async (req: AuthRequest, res: Response, next: NextFunction): Promise<Response | void> => {
    try {
      // 获取当前用户信息
      const user = req.user;
      
      if (!user) {
        return res.status(401).json({
          code: 401,
          msg: '用户未登录'
        });
      }

      // 超级管理员拥有所有权限
      if (user.roles.includes('admin')) {
        next();
        return;
      }
      
      // 检查用户是否有权限标识
      const cacheKey = `perm:${user.userId}:${permission}`;
      
      // 先从缓存中获取
      let hasPermission = permissionCache.get<boolean>(cacheKey);
      
      // 缓存未命中，从数据库检查
      if (hasPermission === undefined) {
        hasPermission = await roleService.hasPermission(user.userId, permission);
        // 将结果存入缓存
        permissionCache.set(cacheKey, hasPermission);
      }
      
      if (!hasPermission) {
        return res.status(403).json({
          code: 403,
          msg: '权限不足，需要特定操作权限'
        });
      }

      next();
      return;
    } catch (error) {
      next(error);
      return;
    }
  };
};

/**
 * 数据权限过滤中间件
 * 根据用户的数据权限范围过滤数据
 */
export const dataScopeMiddleware = () => {
  return async (req: AuthRequest, res: Response, next: NextFunction): Promise<Response | void> => {
    try {
      // 获取当前用户信息
      const user = req.user;
      
      if (!user) {
        return res.status(401).json({
          code: 401,
          msg: '用户未登录'
        });
      }
      
      // 超级管理员拥有所有数据权限
      if (user.roles.includes('admin')) {
        next();
        return;
      }

      // 获取用户数据权限范围
      const cacheKey = `dataScope:${user.userId}`;
      
      // 先从缓存中获取
      let dataScope = permissionCache.get<string[]>(cacheKey);
      
      // 缓存未命中，从数据库获取
      if (!dataScope) {
        dataScope = await roleService.getUserDataScope(user.userId);
        // 将结果存入缓存
        permissionCache.set(cacheKey, dataScope);
      }
      
      // 将数据权限范围添加到请求对象中，供后续业务逻辑使用
      req.dataScope = dataScope.join(',');

      next();
      return;
    } catch (error) {
      next(error);
      return;
    }
  };
};

/**
 * 清除用户权限缓存
 * @param userId 用户ID
 */
export const clearPermissionCache = (userId: number): void => {
  try {
    // 清除以该用户ID为前缀的所有缓存
    const keys = permissionCache.keys().filter((key: string) => key.includes(`${userId}:`));
    keys.forEach((key: string) => permissionCache.del(key));
    logger.info(`已清除用户(${userId})的权限缓存`);
  } catch (error) {
    logger.error(`清除用户权限缓存失败: ${error instanceof Error ? error.message : String(error)}`);
  }
};

/**
 * 重新加载用户权限
 * @param userId 用户ID
 */
export const reloadUserPermissions = async (userId: number): Promise<void> => {
  try {
    // 清除现有缓存
    clearPermissionCache(userId);
    
    // 重新加载权限
    const permissions = await menuService.selectPermsByUserId(userId);
    const dataScope = await roleService.getUserDataScope(userId);
    
    // 更新缓存
    permissions.forEach(permission => {
      const cacheKey = `perm:${userId}:${permission}`;
      permissionCache.set(cacheKey, true);
    });
    
    permissionCache.set(`dataScope:${userId}`, dataScope);
    
    logger.info(`已重新加载用户(${userId})的权限: ${permissions.length}个权限，${dataScope.length}个数据范围`);
  } catch (error) {
    logger.error(`重新加载用户权限失败: ${error instanceof Error ? error.message : String(error)}`);
  }
};

/**
 * 创建权限变更事件监听器
 * @param event 事件名称，如'role_update', 'menu_update', 'user_role_update'等
 * @param handler 处理函数，参数为事件数据，返回需要更新权限的用户ID数组
 * @returns 事件处理函数
 */
export const createPermissionChangeListener = (
  event: string,
  handler: (data: any) => Promise<number[]>
): (data: any) => Promise<void> => {
  // 在实际项目中，可以使用事件发布订阅模式（如EventEmitter）来实现
  // 这里简化为直接返回一个处理函数
  
  // 事件处理函数
  const eventHandler = async (data: any) => {
    try {
      // 调用处理函数获取需要更新权限的用户ID
      const userIds = await handler(data);
      
      // 清除这些用户的权限缓存
      for (const userId of userIds) {
        await reloadUserPermissions(userId);
      }
      
      logger.info(`权限变更事件[${event}]处理完成，已更新${userIds.length}个用户的权限`);
    } catch (error) {
      logger.error(`权限变更事件[${event}]处理失败: ${error instanceof Error ? error.message : String(error)}`);
    }
  };
  
  // 返回事件处理函数
  return eventHandler;
};

/**
 * 应用数据权限过滤条件
 * 根据用户的数据权限范围构建查询条件
 * @param userId 用户ID
 * @param deptAlias 部门表别名
 */
export const getDataScopeCondition = async (userId: number, deptAlias = 'd') => {
  // 获取用户数据权限范围
  const cacheKey = `dataScope:${userId}`;
  
  // 先从缓存中获取
  let dataScope = permissionCache.get<string[]>(cacheKey);
  
  // 缓存未命中，从数据库获取
  if (!dataScope) {
    dataScope = await roleService.getUserDataScope(userId);
    // 将结果存入缓存
    permissionCache.set(cacheKey, dataScope);
  }
  
  // 如果包含全部数据权限，则不需要过滤
  if (dataScope.includes(DATA_SCOPE.ALL)) {
    return {};
  }
  
  // 构建查询条件
  const conditions: any = {};
  
  // 根据不同的数据权限范围构建不同的查询条件
  if (dataScope.includes(DATA_SCOPE.CUSTOM)) {
    // 自定数据权限，需要查询角色和部门关联表
    // 在service层中实现
  } else if (dataScope.includes(DATA_SCOPE.DEPT)) {
    // 本部门数据权限
    // 需要从用户服务或上下文中获取用户部门ID
    conditions[`${deptAlias}.dept_id`] = userId; // 实际实现时应该使用用户的deptId
  } else if (dataScope.includes(DATA_SCOPE.DEPT_AND_CHILD)) {
    // 本部门及以下数据权限
    // 这里需要查询部门及其所有子部门
    // 在service层中实现
  } else if (dataScope.includes(DATA_SCOPE.SELF)) {
    // 仅本人数据权限
    conditions[`create_by`] = userId; // 实际实现时应该使用用户的userName
  }
  
  return conditions;
};